CurseProfiler = {};
CurseProfiler.Data = {};
CurseProfiler.Data.NPCS = {};
CurseProfiler.Data.Quests = {};
CurseProfiler.Data.Mall = {};
CurseProfiler.Data.Objects = {};
CurseProfiler.CurrentZone = nil;
CurseProfiler.LastTarget = nil;
CurseProfiler.LastTargetTimestamp = nil;
CurseProfiler_Save  = nil;
CurseProfiler.Time = 0;
CurseProfiler.Data.StaticLocations = {};
CurseProfiler.Data.Player = {};
CurseProfiler.Version = 20090408;
CurseProfiler.LastX = nil;
CurseProfiler.LastY = nil;
CurseProfiler.RealTime = nil;
local CRAFTINGFRAME_ITEMS = {"BLACKSMITH", "CARPENTER","MAKEARMOR","TAILOR","COOK","ALCHEMY","MINING","LUMBERING","HERBLISM","FISHING"};


local yGather_oldminimapSetZoom = SetMiniMapZoomValue;
yGather_mapzoom = 1;
yGather_SX = 1;
yGather_SY = 1;

yGather_Zones = {
[1]={858,644,"Howling Mountains"},
[2]={1256,942,"Silverspring"},
[4]={1228,921,"Aslan Valley"},
[5]={1532,1149,"Ystra Highlands"},
[6]={1830,1373,"Dust Devil Canyon"},
[10]={1923,1442,"Sascilia Steppes"},
[11]={1600,1200,"Dragonfang Ridge"},
[10001]={539,404,"Obsidian Stronghold City"},
}


CurseProfiler.EquipSlots = {
		"Ring0Slot", "Ring1Slot", "Earring0Slot", "Earring1Slot", "NecklaceSlot",
		"Talisman0Slot", "Talisman1Slot", "Talisman2Slot", "HeadSlot", "ChestSlot",
		"WaistSlot", "LegsSlot", "MainHandSlot", "RangedSlot", "ShoulderSlot", "HandsSlot",
		"FeetSlot", "BackSlot", "SecondaryHandSlot", "AdornmentSlot", "AmmoSlot"};

CurseProfiler.StatNames = {
		"STR", "AGI", "STA", "INT", "MND",
		"MELEE_MAIN_DAMAGE", "MELEE_OFF_DAMAGE", "MELEE_ATTACK", "MELEE_CRITICAL",
		"RANGE_DAMAGE", "RANGE_ATTACK", "RANGE_CRITICAL", "PHYSICAL_PARRY", "PHYSICAL_DEFENCE",
		"MAGIC_DEFENCE", "MAGIC_DAMAGE", "MAGIC_ATTACK", "MAGIC_CRITICAL", "MAGIC_HEAL"};

CurseProfiler.StatIds = {
		2, 6, 3, 4, 5,
		200, 201, 12, 202,
		203, 204, 205, 206, 13,
		14, 207, 15, 208, 209};

CurseProfiler.SupportedObjects = {};
CurseProfiler.SupportedObjects["Abyssal Mercury Ore"] = 1
CurseProfiler.SupportedObjects["Advanced herb"] = 1
CurseProfiler.SupportedObjects["Advanced herb"] = 1
CurseProfiler.SupportedObjects["Advanced herb"] = 1
CurseProfiler.SupportedObjects["Aeontree Wood"] = 1
CurseProfiler.SupportedObjects["Ancient Spirit Oak Wood"] = 1
CurseProfiler.SupportedObjects["Ash Wood"] = 1
CurseProfiler.SupportedObjects["Barsaleaf"] = 1
CurseProfiler.SupportedObjects["Bison Grass"] = 1
CurseProfiler.SupportedObjects["Bitterleaf"] = 1
CurseProfiler.SupportedObjects["Chime Wood"] = 1
CurseProfiler.SupportedObjects["Common herb"] = 1
CurseProfiler.SupportedObjects["Common herb"] = 1
CurseProfiler.SupportedObjects["Common mineral vein"] = 1
CurseProfiler.SupportedObjects["Common mineral vein"] = 1
CurseProfiler.SupportedObjects["Common thicket"] = 1
CurseProfiler.SupportedObjects["Common thicket"] = 1
CurseProfiler.SupportedObjects["Concentrated mineral vein"] = 1
CurseProfiler.SupportedObjects["Concentrated mineral vein"] = 1
CurseProfiler.SupportedObjects["Copper Ore"] = 1
CurseProfiler.SupportedObjects["Cyanide"] = 1
CurseProfiler.SupportedObjects["Dark Crystal"] = 1
CurseProfiler.SupportedObjects["Dragon Beard Root Wood"] = 1
CurseProfiler.SupportedObjects["Dragon Mallow"] = 1
CurseProfiler.SupportedObjects["Dragonlair Wood"] = 1
CurseProfiler.SupportedObjects["Dusk Orchid"] = 1
CurseProfiler.SupportedObjects["Fairywood"] = 1
CurseProfiler.SupportedObjects["Flame Dust"] = 1
CurseProfiler.SupportedObjects["Foloin Nuts"] = 1
CurseProfiler.SupportedObjects["Frost Crystal"] = 1
CurseProfiler.SupportedObjects["Goblin Grass"] = 1
CurseProfiler.SupportedObjects["Good mineral vein"] = 1
CurseProfiler.SupportedObjects["Good mineral vein"] = 1
CurseProfiler.SupportedObjects["Good mineral vein"] = 1
CurseProfiler.SupportedObjects["Green Thistle"] = 1
CurseProfiler.SupportedObjects["Holly Wood"] = 1
CurseProfiler.SupportedObjects["Iron Ore"] = 1
CurseProfiler.SupportedObjects["Maple Wood"] = 1
CurseProfiler.SupportedObjects["Mica"] = 1
CurseProfiler.SupportedObjects["Mine-3"] = 1
CurseProfiler.SupportedObjects["Mirror Sedge"] = 1
CurseProfiler.SupportedObjects["Mithril"] = 1
CurseProfiler.SupportedObjects["Moon Orchid"] = 1
CurseProfiler.SupportedObjects["Moon Silver Ore"] = 1
CurseProfiler.SupportedObjects["Mountain Demon Grass"] = 1
CurseProfiler.SupportedObjects["Moxa"] = 1
CurseProfiler.SupportedObjects["Mysticite"] = 1
CurseProfiler.SupportedObjects["Oak Wood"] = 1
CurseProfiler.SupportedObjects["Pine Wood"] = 1
CurseProfiler.SupportedObjects["Rare thicket"] = 1
CurseProfiler.SupportedObjects["Rare thicket"] = 1
CurseProfiler.SupportedObjects["Red Beet"] = 1
CurseProfiler.SupportedObjects["Redwood"] = 1
CurseProfiler.SupportedObjects["Rock Crystal"] = 1
CurseProfiler.SupportedObjects["Rosemary"] = 1
CurseProfiler.SupportedObjects["Rune Obsidian Ore"] = 1
CurseProfiler.SupportedObjects["Sagewood"] = 1
CurseProfiler.SupportedObjects["Silver Ore"] = 1
CurseProfiler.SupportedObjects["Sinners Palm"] = 1
CurseProfiler.SupportedObjects["Special herb"] = 1
CurseProfiler.SupportedObjects["Special herb"] = 1
CurseProfiler.SupportedObjects["Stone Rotan Wood"] = 1
CurseProfiler.SupportedObjects["Straw Mushroom"] = 1
CurseProfiler.SupportedObjects["Tarslin Demon Wood"] = 1
CurseProfiler.SupportedObjects["Test ore 2 disappears after being depleted"] = 1
CurseProfiler.SupportedObjects["Test ore LV1"] = 1
CurseProfiler.SupportedObjects["Test ore-2"] = 1
CurseProfiler.SupportedObjects["Thorn Apple"] = 1
CurseProfiler.SupportedObjects["Tin Ore"] = 1
CurseProfiler.SupportedObjects["Valuable thicket"] = 1
CurseProfiler.SupportedObjects["Valuable thicket"] = 1
CurseProfiler.SupportedObjects["Valuable thicket"] = 1
CurseProfiler.SupportedObjects["Willow Wood"] = 1
CurseProfiler.SupportedObjects["Wizard-Iron Ore"] = 1
CurseProfiler.SupportedObjects["Yew Wood"] = 1
CurseProfiler.SupportedObjects["Zinc Ore"] = 1




function CurseProfiler_OnLoad(this)
	this:RegisterEvent("LOADING_END");
	this:RegisterEvent("ZONE_CHANGED");
	this:RegisterEvent("UNIT_TARGET_CHANGED");
	this:RegisterEvent("STORE_OPEN");
	this:RegisterEvent("SHOW_QUESTDETAIL_FROM_BOOK");
	this:RegisterEvent("ADDNEW_QUESTBOOK");
	this:RegisterEvent("PLAYER_INVENTORY_CHANGED");
	this:RegisterEvent("SAVE_VARIABLES");
	this:RegisterEvent("IMF_ITEM_UPDATE");
	this:RegisterEvent("MAP_PING");
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("PLAYER_INVENTORY_CHANGED");
	this:RegisterEvent("PLAYER_SKILLED_CHANGED");
	this:RegisterEvent("PLAYER_ABILITY_CHANGED");
	this:RegisterEvent("UNIT_CLASS_CHANGED");
	this:RegisterEvent("UNIT_LEVEL");
	this:RegisterEvent("PLAYER_LIFESKILL_CHANGED");
	this:RegisterEvent("PLAYER_ABILITYPOINT_CHANGED");
	this:RegisterEvent("PLAYER_REGEN_ENABLED");
	this:RegisterEvent("PLAYER_REGEN_DISABLED");
	SaveVariables("CurseProfiler_Save");
	print("CurseProfiler Loaded");
end


local last_save_time = 0
function CurseProfiler_SaveData()
    if CurseProfiler.RealTime - last_save_time < 30 then
        return
    end
    last_save_time = CurseProfiler.RealTime
	CurseProfiler_Save = CurseProfiler.SerializeData();

end

function CurseProfiler_GetNPCID(name)
	for k,v in pairs(CurseProfiler.Data.NPCS) do
		if(v.name == name) then
			return k;
		end

	end
	return nil;
end

function CurseProfiler_GetObjectID(name)
	for k,v in pairs(CurseProfiler.Data.Objects) do
		if(v.name == name) then
			return k;
		end

	end
	return nil;
end

function CurseProfiler_GetResources()	
	local zone = GetCurrentWorldMapID();
	if (yGather_Zones[zone] ~=nil) then
		yGather_SX=yGather_Zones[zone][1];
		yGather_SY=yGather_Zones[zone][2];
	else
		return; -- we have no scaling data for this zone. just exit.
	end

	local px,py = GetPlayerWorldMapPos();
	local rscale = MinimapViewFrame:GetRealScale();
	local minizoom = yGather_mapzoom;
	for i=1,30 do
		local icon=getglobal("MinimapFrame_Icon"..i);
		local txt=GetMinimapIconText(icon:GetID());
		if CurseProfiler.SupportedObjects[txt] ~= nil then
			--print(txt);
			local x,y = icon:GetCenter();
			if(x == nil or y == nil) then

			else
				local xx,yy = MinimapViewFrame:GetCenter();
				x = (x-xx)/rscale/minizoom;
				y = (y-yy)/rscale/minizoom;
	
				-- computing realworld position
				local mx,my = math.floor((px+x/yGather_SX)*1000) / 10.0, math.floor((py+y/yGather_SY)*1000) / 10.0;
				local pos = {x = mx, y = my, zone = CurseProfiler.CurrentZone};
				local objid = CurseProfiler_GetObjectID(txt);
				if(objid == nil) then
					table.insert(CurseProfiler.Data.Objects,{name = txt, pos = {pos}});
				else
					local obj = CurseProfiler.Data.Objects[objid];
					if not HasLocation(obj,pos) then
						table.insert(obj.pos,pos);
				end
			end
			end

		end
	end
	CurseProfiler_SaveData();
end

-- hook for minimap zoom
	SetMiniMapZoomValue = function(zoom)
		yGather_oldminimapSetZoom(zoom);
		yGather_mapzoom=zoom;
--		yecho2("set mini zoom ok "..zoom);
	end

function CurseProfiler_GetQuestID(name)
	for k,v in pairs(CurseProfiler.Data.Quests) do
		if(v.name == name) then
			return k;
		end

	end
	return nil;
end

function CurseProfiler_GetEquipment()
	for _,slot in pairs(CurseProfiler.EquipSlots) do
		local id,id2,id3=GetInventorySlotInfo(slot)

		if GetInventoryItemTexture("player",id) then

			CurseTooltip:SetInventoryItem("player", id)
			CurseTooltip:Hide()
			local name,level,text = CurseProfiler.readTooltip();
			CurseProfiler.Data.Player.Equipment[id] = {name = name, level = level,text = text};
		end
	end
end

function CurseProfiler_GetStats()
	for k,v in pairs(CurseProfiler.StatNames) do
		sval,bval = GetPlayerAbility(v);
		CurseProfiler.Data.Player.Stats[CurseProfiler.StatIds[k]] = sval + bval;
	end
	earth, water, fire, wind, light, dark = GetPlayerResistance();
	CurseProfiler.Data.Player.Stats[27] = earth;
	CurseProfiler.Data.Player.Stats[28] = water;
	CurseProfiler.Data.Player.Stats[29] = fire;
	CurseProfiler.Data.Player.Stats[30] = wind;
	CurseProfiler.Data.Player.Stats[31] = light;
	CurseProfiler.Data.Player.Stats[32] = dark;
	CurseProfiler.Data.Player.Stats[210] = GetPlayerGoodEvil();
	CurseProfiler.Data.Player.Stats[211] = GetPlayerMedalCount();


end

function CurseProfiler_GetSkills()

	for k,v in pairs(PRACTICEDFRAME_ITEMS) do
		level,exlevel,max = GetPlayerSkilled(v);
		CurseProfiler.Data.Player.Skills[k] = {level = level+exlevel,max = max};
	end

end

function CurseProfiler_GetProfessions()

	for k,v in pairs(CRAFTINGFRAME_ITEMS) do
		level = GetPlayerCurrentSkillValue(v);
		max =  GetPlayerMaxSkillValue(v);
		CurseProfiler.Data.Player.Professions[k] = {level = level,max = max};
	end

end

function CurseProfiler_GetGuild()
	local guildName, leaderName, bRecruit, alreadyCreate, MaxMemberCount, Score, GuildNote, Introduce,isLeader, isBBSEnable, isOpenGuild, Level, IsOwnHouse, IsOpenVisit = GetGuildInfo();
	if(guildName == nil) then
		return;
	end
	CurseProfiler.Data.Player.Guild.name = guildName;
	CurseProfiler.Data.Player.Guild.leader = leaderName;
	CurseProfiler.Data.Player.Guild.level = Level;
	for i = 1,GetNumGuildMembers() do
		local name, rank, class, level, subClass, subLevel, isHeader, isCollapsed,dbid,guildTitle ,IsOnLine ,LogOutTime,Zone,Note = GetGuildRosterInfo(i);
		table.insert(CurseProfiler.Data.Player.Guild.members,{name = name, rank = rank, class = class, level = level, subclass = subClass, sublevel = subLevel, title = guildTitle});
	end

end

function CurseProfiler_GetRecipes()
	local _NumCraftSkill = GetCraftItemList( -1 );
	for i = 1,_NumCraftSkill do
		if _NumCraftSkill ~= 0 then
			local CraftTypeID = GetCraftItemType(i);
			local _NumItem = GetCraftItem(i,1,-1);
			for j = 1,_NumItem do
				local _CatalogID, _CraftItemName, _Act, _GUID = GetCraftItem( i, 1,  j );
				table.insert(CurseProfiler.Data.Player.Recipes,_GUID);				

			end

		end

	end

end



function CurseProfiler_GetPlayer()
	local player = {Equipment = {},Stats = {},Skills = {},Professions = {}, Guild = {members={}}, Recipes = {}};
	player.name= UnitName("player");
	player.server = CurseProfiler_GetServer();
	player.sex = UnitSex("player");
	mainClass, subClass = UnitClass("player");
	player.mainClass = mainClass;
	player.subClass = subClass or "";
	player.mainLevel = 0;
	player.subLevel = 0;
	for i = 1,GetPlayerNumClasses() do
		local class, _, level,current,max = GetPlayerClassInfo(i,true);
		if class == player.mainClass then
			player.mainLevel = level;
			player.mainXP = current;
			player.mainMaxXP = max;
		elseif class == player.subClass then
			player.subLevel = level;
			player.subXP = current;
			player.subMaxXP = max;
		end
	end
	CurseProfiler.Data.Player = player;
	CurseProfiler_GetEquipment();
	CurseProfiler_GetStats();
	CurseProfiler_GetSkills();
	CurseProfiler_GetProfessions();
	CurseProfiler_GetGuild();
	CurseProfiler_GetRecipes();
	if(CurseProfiler.Data.Player.Guild.name ~= nil) then
		CurseProfiler.Data.Player.guild = CurseProfiler.Data.Player.Guild.name;
	else
		CurseProfiler.Data.Player.guild = "";
	end
	CurseProfiler.Data.Server = {name = player.server};
	CurseProfiler_SaveData()
end

function CurseProfiler_GetServer()
	local s = GetCurrentRealm()
	s = string.gsub(s, "^.*|r%s+","")
	s = string.gsub(s, "%[[%w%s]*%]","")
	s = string.gsub(s, "%s+$","")
	return s
end

function CurseProfiler.readTooltip()
	local level = "1";
	local s = "";
	local text = "";
	for i = 1, 40 do
		leftLine = getglobal("CurseTooltipTextLeft" .. i);
		rightLine = getglobal("CurseTooltipTextRight" .. i);
		left, right = "", "";
		if leftLine:IsVisible() then left = leftLine:GetText() end
		if rightLine:IsVisible() then right = rightLine:GetText() end
		if left~="" or right~="" then
			if left == nil then
				left = "";
			end
			if right == nil then
				right = "";
			end
			if i == 1 and left ~= nil then
				local names= CurseProfiler.string.split(left,"+");
				if names[1] ~= nil then
					s = s .. names[1];
				elseif left ~= nil then
					s = s.. left
				end
			end
			if left ~= nil then
				if string.find(left,"Requires Level") ~= nil then
					local results = CurseProfiler.string.split(left,"Requires Level ");
					if results ~= nil then
						level = results[2];							
					end
				end
			end
			local r,g,b = leftLine:GetColor();
			local leftColor = string.format('%02X%02X%02X',r*255,g*255,b*255);
			r,g,b = rightLine:GetColor();
			local rightColor = string.format('%02X%02X%02X',r*255,g*255,b*255);
			text = text .. left.."|"..leftColor.."|"..right.."|"..rightColor..";";
		end
	end
	return s,level,text;
end

function CurseProfiler_OnEvent(this,event,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
	if(event == "ZONE_CHANGED") then
		CurseProfiler.CurrentZone = GetZoneID();
		testtrack();
		
	elseif(event == "UNIT_TARGET_CHANGED") then
		CurseProfiler_TargetChange(arg1,arg2);
	elseif(event == "STORE_OPEN") then
		CurseProfiler_HandleStore(arg1,arg2,arg3);
	elseif(event == "ADDNEW_QUESTBOOK") then
		--CurseProfiler_HandleQuest(arg1);
	elseif(event == "LOADING_END") then
		testtrack();
		--CurseProfiler_GetPlayer();
	elseif(event == "SHOW_QUESTDETAIL_FROM_BOOK") then
		CurseProfiler_HandleBookQuest(arg1);
	elseif(event == "PLAYER_INVENTORY_CHANGED") then
		--print(arg1);
	elseif(event == "SAVE_VARIABLES") then
		CurseProfiler_SaveData();
	elseif(event == "IMF_ITEM_UPDATE") then
		CurseProfiler_CollectMall();
	elseif(event == "MAP_PING") then
	elseif(event == "VARIABLES_LOADED") then
	elseif(event == "PLAYER_INVENTORY_CHANGED") then
		CurseProfiler_GetPlayer();
	elseif(event == "PLAYER_SKILLED_CHANGED") then
		CurseProfiler_GetPlayer();
	elseif(event == "PLAYER_ABILITY_CHANGED") then
		CurseProfiler_GetPlayer();
	elseif(event == "UNIT_CLASS_CHANGED") then
		CurseProfiler_GetPlayer();
	elseif(event == "UNIT_LEVEL") then
		CurseProfiler_GetPlayer();
	elseif(event == "PLAYER_LIFESKILL_CHANGED") then
		CurseProfiler_GetPlayer();
	elseif(event == "PLAYER_ABILITYPOINT_CHANGED") then
		CurseProfiler_GetPlayer();
	elseif(event == "PLAYER_REGEN_ENABLED") then
		CurseProfiler_LeaveCombat();
	elseif(event == "PLAYER_REGEN_DISABLED") then
		CurseProfiler_EnterCombat();
	end
	

end

function CurseProfiler_HandleBookQuest(index)
			index2, catalogID, name, track, level, daily = GetQuestInfo(index);
	local quest = {};
	quest.name = name;
	quest.catalog = catalogID;
	quest.daily = daily;
	quest.startnpc = QuestDetail_GetQuestNPC();
	quest.endnpc = QuestDetail_GetRequestQuestNPC();
	quest.xp = GetQuestExp_QuestDetail();
	quest.tp = GetQuestTP_QuestDetail();
	quest.money = GetQuestMoney_QuestDetail();
	local id = CurseProfiler_GetQuestID(quest.name);
	if(id ~= nil) then
		CurseProfiler.Data.Quests[id] = quest;
	else
		table.insert(CurseProfiler.Data.Quests,quest);
	end
end


function CurseProfiler_CollectMall()
--only collect diamond items
if ItemMallFrame.SelectType ~= 3 then
	return;
end
local count=CIMF_GetNums();
for item_num = 1,count do
	local GUID,name,textureName,Nums,icon,diamond,bouns,free,freed_bouns,flash,count,CountMsg,TimeMsg,Detail,atCount=CIMF_GetItemInfo(item_num,-1);
	CurseProfiler.Data.Mall[name] = {diamonds= diamond, count = count}
	
end
	CurseProfiler_SaveData()
end

function testtrack()
	local count = NpcTrack_SearchNpc(""); 
	for i=1 , count do
		npcID, name, mapID, x, y = NpcTrack_GetNpc(i);
		if(x == nil or y == nil) then

		else
			CurseProfiler.Data.StaticLocations[npcID] = {x = x*100.0, y = y*100.0, zone = mapID};
		
		end

	end
	count = NpcTrack_SearchQuestNpc( true , false );
	for i=1 , count do
		npcID, name, mapID, x, y = NpcTrack_GetNpc(i);
		if(x == nil or y == nil) then
		else
			CurseProfiler.Data.StaticLocations[npcID] = {x = x*100.0, y = y*100.0, zone = mapID};
		end
		
	end
	--print("collected zone locs");
	CurseProfiler_SaveData()
end

function CurseProfiler_HandleQuest(index)
	local quest = {};
	index, catalogID, name, track, level, daily = GetQuestInfo(questid);
	quest.id = questid;
	quest.catalog = catalogID;
	quest.daily = daily;
	quest.money = GetQuestMoney_QuestDetail();
	quest.tp = GetQuestTP_QuestDetail();
	quest.xp = GetQuestExp_QuestDetail();
	CurseProfiler.Data.Quests[quest.id] = quest;
	CurseProfiler_SaveData()
end

function CurseProfiler_GetIDFromLink(link)
	local p1,p2,data,name = string.find(link,'|Hitem:([^|]+)|h|[%l%d]+%[([^%]]*)%]|r|h');
	local attr = {};
	
	local dataParts = {};
	for val in string.gmatch(data,"[%a%d]+") do
		dataParts[#dataParts+1] = tonumber(val,16);
	end
	return dataParts[1];


end

function CurseProfiler_HandleStore(arg1,arg2,arg3)
	if(CurseProfiler.LastTarget == nil) then
		return
	end
	local mobid = CurseProfiler_GetNPCID(CurseProfiler.LastTarget);
	if(mobid == nil) then
		return;
	end
	local mob = CurseProfiler.Data.NPCS[mobid];
	for i = 1,GetStoreSellItems() do
		local icon, name, price, cashType = GetStoreSellItemInfo(i);
		local link = GetStoreSellItemLink(i);
		local id= CurseProfiler_GetIDFromLink(link);
		if(id ~= nil) then
			table.insert(mob.store,{id = id,price = price,type = cashType});
		end
	end
	CurseProfiler_SaveData();
end

local in_combat = false
local function gc_hack(elapsed)
	if not in_combat and elapsed < 1/30 then
		collectgarbage('step')
	end
end

function CurseProfiler_EnterCombat()
	in_combat = true
end
function CurseProfiler_LeaveCombat()
	in_combat = false
end

CurseProfiler.RealTime = GetTime();
function CurseProfiler_OnUpdate()
	local now = GetTime()
	local elapsed = CurseProfiler.RealTime - now;
	CurseProfiler.RealTime = now;

	gc_hack(elapsed)
	--if(elapsed ~= nil and type(elapsed) == "number") then
	--	CurseProfiler.Time = CurseProfiler.Time + elapsed;
	--end
	CurseProfiler.Time = CurseProfiler.Time + 1;
	if(CurseProfiler.Time == 300) then
		CurseProfiler_GetPlayer();
	end
	local x,y = GetPlayerWorldMapPos();
	if(x == nil or y == nil or CurseProfiler.LastX == nil or CurseProfiler.LastY == nil) then
		return;
	end 
	if(CurseProfiler.LastX ~= nil) then
		if((x <= CurseProfiler.LastX + 0.03) and (x >= CurseProfiler.LastX - 0.03) and (y <= CurseProfiler.LastY + 0.03) and (y >= CurseProfiler.LastY - 0.03)) then
		else
			CurseProfiler_GetResources();
			CurseProfiler.LastX = x;
			CurseProfiler.LastY = y;
		end
	else
		CurseProfiler_GetResources();
		CurseProfiler.LastX = x;
		CurseProfiler.LastY = y;
	end


end

function print(message)
	if (DEFAULT_CHAT_FRAME) then
		DEFAULT_CHAT_FRAME:AddMessage(tostring(message));
	end
end

function HasLocation(mob,pos)
	for k,v in pairs(mob.pos) do
		if((pos.x <= v.x + 0.3) and (pos.x >= v.x - 0.3) and (pos.y <= v.y + 0.3) and (pos.y >= v.y - 0.3) and (pos.zone == v.zone)) then
			return true;
		end
	end
	return false;
end


function CurseProfiler_TargetChange(arg1,arg2)
	if arg1=="player" then
		if(arg2==0) then
			return;
		end
	end
	if UnitIsPlayer("target")or UnitIsDeadOrGhost("target") then
		return;
	end
	local target=UnitName("target")
	if(target == nil) then
		return;
	end
	local class=UnitClass("target")
	local level=UnitLevel("target")
	local health=UnitChangeHealth("target")
	local skill=UnitSkill("target")
	local maxSkill=UnitMaxSkill("target")
	local sex=UnitSex("target")
	local skillType=UnitSkillType("target")
	local distance = UnitDistance("target");
	local MobID = CurseProfiler_GetNPCID(target);
	local x,y = GetPlayerWorldMapPos();
	local pos = {};
	if(x == nil) then
		x = 0;
	end

	if(y == nil) then
		y = 0;
	end
	pos.x = x*100.0;
	pos.y = y * 100.0;
	pos.zone = CurseProfiler.CurrentZone;
	CurseProfiler.LastTarget = target;
	CurseProfiler.LastTargetTimestamp = CurseProfiler.Time;
	if(MobID == nil) then
		local mob = {};
		mob.name = target;
		mob.class = class;
		mob.minlevel = level;
		mob.maxlevel = level;
		mob.loot = {};
		mob.store = {};
		mob.pos = {};
		if(x == 0 and y == 0) then

		else
			table.insert(mob.pos,pos);
		end
		
		table.insert(CurseProfiler.Data.NPCS,mob);
	else
		local mob = CurseProfiler.Data.NPCS[MobID];
		if(x == 0 and y == 0) then

		else
			if(not HasLocation(mob,pos)) then
				table.insert(mob,pos);
			end
		end

	end
	CurseProfiler_SaveData()

end

CurseProfiler.string = {};

CurseProfiler.string.split = function(str, delim)
    if not delim then
        delim = " "
    end
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gfind(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
    end
    -- Handle the last field
    result[nb + 1] = string.sub(str, lastPos)
    return result
end



function CurseProfiler_SerializeData()
	


end